﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Sl.Support.Forms;
using Sl.Log;
using Sl.Support.McuBytes;
using ChholCmdPort;

namespace ChholConfig.Configer {
	public partial class Configer : PortUserForm {
		public Configer() : base() {
			InitializeComponent();
		}
		readonly Image Addr_inc_off = global::ChholConfig.Properties.Resources.add_text_50px;
		readonly Image Addr_inc_on = IconRecolor.reColorPng(global::ChholConfig.Properties.Resources.add_text_50px, Color.DodgerBlue);
		Logger logger;
		bool auto_inc = false;

		public Configer(RecvFanOut fan_out, Form main_form)
			: base(global::ChholConfig.Properties.Resources.desktop_download_50px, 20, fan_out, "组网参数配置器") {
			InitializeComponent();
			logger = new LoggerToRTB(LogRTB);
			configTS.Enabled = commonTS.Enabled = false;
		}
		protected override void turnOn() {
			configTS.Enabled = commonTS.Enabled = true;
		}
		private void doConfig(object sender, EventArgs e) {
			var a = (ushort)AddrTB.Num;
			var p = (ushort)PanidTB.Num;
			var c = (ushort)ChannleTB.Num;

			if (a >= 0xF000) {
				logger.LogLine($"【错误】地址必须小于0xF000。");
				return;
			}
			if (p == 0x00ff) {
				logger.LogLine($"【错误】网络ID不能取广播ID（0x00ff）。");
				return;
			}
			logger.LogLine($"【消息】即将设置当前模块到：{showParament((ushort)a, (ushort)p, (ushort)c)}。");
			setToMModel();
			setAddr((ushort)a);
			setPanid((ushort)p);
			setChannle((ushort)c);
			logger.LogLine($"【消息】配置成功了。");
			if (auto_inc) {
				AddrTB.Num = a + 1;
			}
		}
		private string showParament(ushort a, ushort p, ushort c) {
			return $"地址 = 0x{a:x4}；网络ID = 0x{p:x4}；信道 = {c}";
		}
		private void readInformationBTN_Click(object sender, EventArgs e) {
			Pkg p = new Pkg();
			p.To_port = 103;
			p.Remote_addr = 0xfff0;
			p.loadData((byte)'R');

			ushort get_addr = 0;
			ushort get_panid = 0;
			ushort get_channle = 0xffff;
			using (var pkg_recv_event = new System.Threading.AutoResetEvent(false)) {
				Port_user.dRecvPkg = pkg => {
					if (pkg[0] != (byte)'r') {
						return false;
					}
					int i = 1;
					get_addr = Ushort_Expand.ToUint16(pkg[i], pkg[i + 1]); i += 2;
					get_panid = Ushort_Expand.ToUint16(pkg[i], pkg[i + 1]); i += 2;
					get_channle = pkg[i++];
					pkg_recv_event?.Set();
					return true;
				};
				Port_user.sendPkg(p);
				if (pkg_recv_event.WaitOne(500) == true) {
					logger.LogLine($"【消息】读取到模块的网络配置信息：{showParament(get_addr, get_panid, get_channle)}。");
				} else {
					logger.LogLine($"【警告】没有读到当前模块的地址信息");
				}
			}
		}

		private bool setToMModel() {
			Pkg p = new Pkg();
			p.To_port = 104;
			p.Remote_addr = 0xfff0;
			p.loadData((byte)'M', 0x95, 0xc4);

			using (var pkg_recv_event = new System.Threading.AutoResetEvent(false)) {
				Port_user.dRecvPkg = pkg => {
					if (pkg[0] != (byte)'M') {
						return false;
					}
					if (pkg[1] == 0) {
						pkg_recv_event?.Set();
					} else if (pkg[1] == 3) {//重复命令，命令要求的状态和现在相同。
						pkg_recv_event?.Set();
					}
					return true;
				};
				Port_user.sendPkg(p);
				if (pkg_recv_event.WaitOne(1000) == true) {
					return true;
				} else {
					logger.LogLine($"【警告】设置为自定义模式失败了");
					return false;
				}
			}
		}
		private bool setToUndefined() {
			Pkg p = new Pkg();
			p.To_port = 104;
			p.Remote_addr = 0xfff0;
			p.loadData((byte)'U', 0x95, 0xc4);

			using (var pkg_recv_event = new System.Threading.AutoResetEvent(false)) {
				Port_user.dRecvPkg = pkg => {
					if (pkg[0] != (byte)'U') {
						return false;
					}
					if (pkg[1] == 0) {
						pkg_recv_event?.Set();
					} else if (pkg[1] == 3) {//重复命令，命令要求的状态和现在相同。
						pkg_recv_event?.Set();
					}
					return true;
				};
				Port_user.sendPkg(p);
				if (pkg_recv_event.WaitOne(1000) == true) {
					return true;
				} else {
					logger.LogLine($"【警告】设置为未定义模式失败了");
					return false;
				}
			}
		}
		private bool setToCoordinator() {
			Pkg p = new Pkg();
			p.To_port = 104;
			p.Remote_addr = 0xfff0;
			p.loadData((byte)'C');

			using (var pkg_recv_event = new System.Threading.AutoResetEvent(false)) {
				Port_user.dRecvPkg = pkg => {
					if (pkg[0] != (byte)'C') {
						return false;
					}
					if (pkg[1] == 0) {
						pkg_recv_event?.Set();
					} else {
					}
					return true;
				};
				Port_user.sendPkg(p);
				if (pkg_recv_event.WaitOne(1000) == true) {
					return true;
				} else {
					logger.LogLine($"【警告】设置为协调器模式失败了");
					return false;
				}
			}
		}
		private bool setAddr(ushort addr) {
			Pkg p = new Pkg();
			p.To_port = 103;
			p.Remote_addr = 0xfff0;
			p.loadData((byte)'A', addr.ByteLow(), addr.ByteHigh());

			using (var pkg_recv_event = new System.Threading.AutoResetEvent(false)) {
				Port_user.dRecvPkg = pkg => {
					if (pkg[0] != (byte)'A') {
						return false;
					}
					if (pkg[1] == 0)
						pkg_recv_event?.Set();
					else {
					}
					return true;
				};
				Port_user.sendPkg(p);
				if (pkg_recv_event.WaitOne(1000) == true) {
					return true;
				} else {
					logger.LogLine($"【警告】设置地址失败了");
					return false;
				}
			}
		}
		private bool setPanid(ushort PanID) {
			Pkg p = new Pkg();
			p.To_port = 103;
			p.Remote_addr = 0xfff0;
			p.loadData((byte)'P', PanID.ByteLow(), PanID.ByteHigh());

			using (var pkg_recv_event = new System.Threading.AutoResetEvent(false)) {
				Port_user.dRecvPkg = pkg => {
					if (pkg[0] != (byte)'P') {
						return false;
					}
					if (pkg[1] == 0) {
						pkg_recv_event?.Set();
					} else {
					}
					return true;
				};
				Port_user.sendPkg(p);
				if (pkg_recv_event.WaitOne(1000) == true) {
					return true;
				} else {
					logger.LogLine($"【警告】设置网络ID失败了");
					return false;
				}
			}
		}
		private bool setChannle(ushort channle) {
			Pkg p = new Pkg();
			p.To_port = 103;
			p.Remote_addr = 0xfff0;
			p.loadData((byte)'C', (byte)channle);
			using (var pkg_recv_event = new System.Threading.AutoResetEvent(false)) {
				Port_user.dRecvPkg = pkg => {
					if (pkg[0] != (byte)'C') {
						return false;
					}
					if (pkg[1] == 0) {
						pkg_recv_event?.Set();
					} else {
					}
					return true;
				};
				Port_user.sendPkg(p);
				if (pkg_recv_event.WaitOne(1000) == true) {
					return true;
				} else {
					logger.LogLine($"【警告】设置信道失败了");
					return false;
				}
			}
		}

		private bool setToAddrDistributor(bool is_open) {
			byte cmd = is_open ? (byte)'A' : (byte)'Q';
			Pkg p = new Pkg();
			p.To_port = 105;
			p.Remote_addr = 0xfff0;
			p.loadData(cmd);
			using (var pkg_recv_event = new System.Threading.AutoResetEvent(false)) {
				Port_user.dRecvPkg = pkg => {
					if ((pkg[0] != cmd)) {
						return false;
					}
					if ((pkg[1] == 0)) {
						pkg_recv_event?.Set();
					} else {
					}
					return true;
				};
				Port_user.sendPkg(p);
				if (pkg_recv_event.WaitOne(1000) == true) {
					if (is_open) {
						Port_user.dRecvPkg = pkg => {
							if (pkg[0] != (byte)'n') {
								return false;
							} else {
								logger.LogLine($"【消息】新节点加入，为其设置了地址={Ushort_Expand.ToUint16(pkg[1], pkg[2])}");
								return true;
							}
						};
					}
					return true;
				} else {
					logger.LogLine($"【警告】设置地址分配器的状态失败了。");
					return false;
				}
			}
		}
		private void autoIncrease_click(object sender, EventArgs e) {
			if (auto_inc) {
				auto_inc = false;
				autoIncreaseBT.Image = Addr_inc_off;
				logger.LogLine($"【消息】已经关闭了地址自动加一。");
			} else {
				auto_inc = true;
				autoIncreaseBT.Image = Addr_inc_on;
				logger.LogLine($"【消息】设置为地址自动加一。");
			}
		}

		private void setToCoordinatorBT_Click(object sender, EventArgs e) {
			logger.LogLine($"【消息】设置为协调器。");
			setToUndefined();
			setToCoordinator();
		}

		private void turnOnAddrDistributorBT_Click(object sender, EventArgs e) {
			logger.LogLine($"【消息】启动地址分配器。");
			setToAddrDistributor(true);
		}

		private void turnOffAddrDistributorBT_Click(object sender, EventArgs e) {
			logger.LogLine($"【消息】退出地址分配器");
			setToAddrDistributor(false);
		}

		private void readConfigBTN_Click(object sender, EventArgs e) {

			Pkg p = new Pkg();
			p.To_port = 103;
			p.Remote_addr = 0xfff0;
			p.loadData((byte)'R');

			ushort get_addr = 0;
			ushort get_panid = 0;
			ushort get_channle = 0xffff;
			using (var pkg_recv_event = new System.Threading.AutoResetEvent(false)) {
				Port_user.dRecvPkg = pkg => {
					if (pkg[0] != (byte)'r') {
						return false;
					}
					int i = 1;
					get_addr = Ushort_Expand.ToUint16(pkg[i], pkg[i + 1]); i += 2;
					get_panid = Ushort_Expand.ToUint16(pkg[i], pkg[i + 1]); i += 2;
					get_channle = pkg[i++];
					pkg_recv_event?.Set();
					return true;
				};
				Port_user.sendPkg(p);
				if (pkg_recv_event.WaitOne(500) == true) {
					this.AddrTB.Text = get_addr.ToString("X4");
					this.PanidTB.Text = get_panid.ToString("X4");
					this.ChannleTB.Text = get_channle.ToString();

				} else {
					logger.LogLine($"【警告】没有读到当前模块的地址信息");
				}
			}
		}
	}
}
